#include <dim-sum/amba/bus.h>
#include <dim-sum/amba/serial.h>
#include <dim-sum/beehive.h>
#include <dim-sum/errno.h>
#include <dim-sum/init.h>
#include <dim-sum/irq.h>
#include <dim-sum/irq_mapping.h>
#include <dim-sum/serial.h>
#include <dim-sum/simple_console.h>
#include <dim-sum/workqueue.h>
#include <asm/memory.h>
#include <asm/io.h>

#include <dim-sum/linkage.h>
#include <dim-sum/types.h>

#include <dim-sum/cache.h>
#include <dim-sum/devtree.h>
#include <dim-sum/printk.h>
#include <dim-sum/delay.h>
#include <dim-sum/console.h>

#include <dim-sum/serial_reg.h>
#include <asm/io.h>
#include "ns16550a.h"
/* 波特率计算公式：Baud = Clock / (16 * Divisor) */
uint16_t divisor = 0;       // 用于存储波特率分频系数

/* 接收一个字符 */
static char real_serial_ns16550a_getc(uint64_t base_addr)
{
    while ((readb((volatile void*)(base_addr + UART_LSR)) & UART_LSR_DR) == 0)
        ;  // 等待接收缓冲区非空
    return readb((volatile void*)(base_addr + UART_RX));
}

/* 初始化串口设备 */
__maybe_unused static void serial_ns16550a_init(uint32_t baud_rate)
{
	// real_serial_ns16550a_init(UART_BASE_ADDR, baud_rate);
}

static void real_serial_ns16550a_putc(uint64_t base_addr, char c)
{   
    while ((readb((volatile void*)(base_addr + UART_LSR)) & UART_LSR_THRE) == 0)
        ;  // 等待发送缓冲区为空
    writeb(c, (volatile void*)(base_addr + UART_TX));
}


__maybe_unused static char serial_ns16550a_getc(void)
{
	return real_serial_ns16550a_getc(UART_BASE_ADDR);
}

static void serial_ns16550a_putc(char c, void *addr)
{
	real_serial_ns16550a_putc((uint64_t)addr, c);
}

/* 初始化串口设备 */
__maybe_unused static void real_serial_ns16550a_init(uint64_t base_addr, uint32_t baud_rate)
{
	uint16_t divisor_value = 0;
   	uint8_t lcr_value = 0;

	/* 计算波特率分频系数 */
	divisor_value = 115200 / baud_rate;
	divisor = divisor_value;

	/* 禁用中断 */
	writeb(0x00, (volatile void*)(base_addr + UART_IER));

	/* 设置波特率 */
	lcr_value = readb((volatile void*)(base_addr + UART_LCR));
	writeb(lcr_value | UART_LCR_DLAB, (volatile void*)(base_addr + UART_LCR));
	writeb(divisor_value & 0xff, (volatile void*)(base_addr + UART_DIV_LATCH_LOW));
	writeb((divisor_value >> 8) & 0xff, (volatile void*)(base_addr + UART_DIV_LATCH_HIGH));
	writeb(lcr_value, (volatile void*)(base_addr + UART_LCR));

	/* 设置数据位、停止位、校验位等参数 */
	writeb(0x03, (volatile void*)(base_addr + UART_LCR));   // 8 数据位，1 停止位，无校验
	writeb(0xc7, (volatile void*)(base_addr + UART_MCR));   // 打开 DTR、RTS 和 OUT2 信号

	/* 清空串口缓冲区 */
	while (readb((volatile void*)(base_addr + UART_LSR)) & UART_LSR_DR)
		readb((volatile void*)(base_addr + UART_RX));
}

static void ns16550a_simple_write(struct console *con,
const char *s, unsigned count)
{
	struct simple_console_device *device = con->data; 
	unsigned int i;

	for (i = 0; i < count; i++, s++) {
		if (*s == '\n')
			serial_ns16550a_putc('\r', device->membase);
		serial_ns16550a_putc(*s, device->membase);
	}
}

static int __init ns16559a_init_simple(struct simple_console_device *device, void *opt)
{

    
#if defined(CONFIG_ARCH_RV64I)
	/**
	 * device->membase 已经在simple_console_map中被映射，这里无需或上一个偏移
     * device->membase = UART_BASE_ADDR | 0x9000000000000000;
	 */
    
#else
    device->membase = (void*)(UART_BASE_ADDR | 0x9000000000000000UL);
#endif

    // real_serial_ns16550a_init((uint64_t)device->membase, 0x384000);

	device->con->write = ns16550a_simple_write;
    
	return 0;
}



const struct simple_console_id simple_console_ns16550a = {
				.name  = "ns16550a",
				.init = ns16559a_init_simple,
			};

